package net.pinnoocle.playservice.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import net.pinnoocle.playcommon.constant.Constant;
import net.pinnoocle.playcommon.exception.ShopException;
import net.pinnoocle.playcommon.response.ErrorCode;
import net.pinnoocle.playcommon.utils.ConvertUtils;
import net.pinnoocle.playcommon.utils.HelpUtils;
import net.pinnoocle.playdao.dao.GroupDao;
import net.pinnoocle.playdao.entity.*;
import net.pinnoocle.playdao.entity.page.PageModel;
import net.pinnoocle.playdao.entity.page.PageQuery;
import net.pinnoocle.playdao.entity.shopPc.group.SaveGroupParams;
import net.pinnoocle.playdao.entity.shopPc.group.ShopGroupListPageVo;
import net.pinnoocle.playdao.entity.shopPc.group.ShopGroupListSearchParams;
import net.pinnoocle.playdao.entity.shopPc.group.ShopPcGroupDetailVo;
import net.pinnoocle.playdao.entity.web.QrCodeVo;
import net.pinnoocle.playdao.entity.web.group.*;
import net.pinnoocle.playdao.entity.web.master.MasterGroupListVo;
import net.pinnoocle.playdao.entity.web.user.homepage.RecommendGroupVo;
import net.pinnoocle.playservice.service.CommonService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 组局表(Group)表服务实现类
 *
 * @author ye
 * @since 2021-10-25 10:24:01
 */
@Service("groupService")
@Slf4j
public class GroupServiceImpl extends ServiceImpl<GroupDao, Group> {

    @Autowired
    ShopServiceImpl shopService;
    @Autowired
    UserServiceImpl userService;
    @Autowired
    UserGroupServiceImpl userGroupService;
    @Autowired
    ScriptServiceImpl scriptService;
    @Autowired
    UserAppointOrderServiceImpl userAppointOrderService;
    @Autowired
    CommonService commonService;
    @Autowired
    ShopStatisticsServiceImpl shopStatisticsService;
    @Autowired
    ShopUserServiceImpl shopUserService;

    /**
     * 店铺组局列表
     * @param params
     * @return
     */
    public PageModel<ShopGroupListPageVo> shopGroupList(ShopGroupListSearchParams params){
        Map<String,Object> pageMap = new HashMap<>();
        pageMap.put("page",String.valueOf(params.getPage()));
        pageMap.put("pageSize",String.valueOf(params.getPageSize()));

        if(params.getShopId() == null){
            params.setShopId(shopService.getShopId());
        }
        Page<ShopGroupListPageVo> list = this.baseMapper.shopGroupList(
                new PageQuery<Group>(pageMap).getPage(),params);
        List<ShopGroupListPageVo> records = list.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageModel<>(list, new ArrayList<>());
        }
        for (ShopGroupListPageVo item : records){
            String cateNames = scriptService.getNamesByIds(item.getScriptCateId(), 0);
            item.setScriptCateName(cateNames);
            String labelNames = scriptService.getNamesByIds(item.getScriptLabelId(), 1);
            item.setScriptLabelName(labelNames);
            String levelNames = scriptService.getNamesByIds(item.getScriptLevelId(), 2);
            item.setScriptLevelName(levelNames);
            //预计结束
            if(Objects.nonNull(item.getScriptTime())){
                int scriptMinutes = (int) (item.getScriptTime()*60);
                Date endTime = HelpUtils.afterTime(item.getStartTime(),scriptMinutes);
                item.setEndTime(endTime);
            }
        }
        return new PageModel<>(list, records);
    }

    /**
     * 店铺组局
     * @param params
     * @return
     */
    public boolean saveGroup(SaveGroupParams params){
        String shopId = shopService.getShopId();
        Script script = scriptService.getById(params.getScriptId());
        if(Objects.isNull(script)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"剧本不存在");
        }
        if(script.getIsDisable() == 1){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"剧本被禁用");
        }
        try {
            Group group = ConvertUtils.sourceToTarget(params, Group.class);
            group.setShopId(shopId);
            group.setStartNumber(script.getStartNumber());
            group.setCreatedTime(new Date());
            return this.save(group);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("组局失败："+e.getMessage());
            return false;
        }
    }

    /**
     * 组局信息
     * @param groupId
     * @return
     */
    public ShopPcGroupDetailVo groupDetail(String groupId){
        return this.baseMapper.shopGroupDetail(groupId);
    }

    /**
     * 组局信息---后台
     * @param groupId
     * @return
     */
    public GroupDetailVo groupDetailForShopPc(String groupId){
        GroupDetailVo groupDetailVo = this.baseMapper.webGroupDetail(groupId);
        //ids换取names
        String cateNames = scriptService.getNamesByIds(groupDetailVo.getScriptCateId(), 0);
        groupDetailVo.setScriptCateName(cateNames);
        int scriptMinutes = (int) (groupDetailVo.getScriptTime()*60);
        Date endTime = HelpUtils.afterTime(groupDetailVo.getStartTime(),scriptMinutes);
        groupDetailVo.setEndTime(endTime);
        return groupDetailVo;
    }

    /**
     * 店铺重新组局
     * @param params
     * @return
     */
    public boolean updateGroup(SaveGroupParams params){
        String groupId = params.getGroupId();
        Group groupInfo = this.getById(groupId);
        if(Objects.isNull(groupInfo)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"组局不存在");
        }
        Script script = scriptService.getById(groupInfo.getScriptId());
        if(Objects.isNull(script)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"剧本不存在");
        }
        if(script.getIsDisable() == 1){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"剧本被禁用");
        }
        try {
            Group group = ConvertUtils.sourceToTarget(params, Group.class);
            group.setStartNumber(script.getStartNumber());
            return this.updateById(group);
        } catch (Exception e) {
            log.info("重新组局失败："+e.getMessage());
            return false;
        }
    }

    /**
     * 移除组局
     * @param groupId
     * @return
     */
    public boolean deleteGroup(String groupId){
        try {
            return this.removeById(groupId);
        } catch (Exception e) {
            log.info("移除组局失败："+e.getMessage());
            return false;
        }
    }

    /**
     * 定金下单
     * @param groupId
     * @return
     */
    public String userJoinGroup(String groupId){
        String userId = userService.getUserId();
        UserGroup userGroup = userGroupService.getOne(new QueryWrapper<UserGroup>()
                .lambda()
                .eq(UserGroup::getUserId, userId)
                .eq(UserGroup::getIsPay, 0));
        if(Objects.nonNull(userGroup)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"还有一笔未支付的订单，请先完成支付！");
        }
        Group group = this.getById(groupId);
        if(Objects.isNull(group)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"组局不存在");
        }
        if(group.getGroupType() > 0){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"本局人数已满");
        }
        try {
            UserAppointOrder appointOrder = new UserAppointOrder();
            String orderNumber = HelpUtils.getOrderNumber();
            appointOrder.setOrderNo(orderNumber);
            appointOrder.setUserId(userId);
            appointOrder.setGroupId(groupId);
            appointOrder.setShopId(group.getShopId());
            appointOrder.setPayAmount(Constant.APPOINT_AMOUNT);
            appointOrder.setCreatedTime(new Date());
            boolean result = userAppointOrderService.save(appointOrder);
            if(result){
                return appointOrder.getAppointId();
            }
        } catch (Exception e) {
            log.info("用户加入组局失败："+e.getMessage());
        }
        return null;
    }

    /**
     * 定金支付成功，用户加入组局
     * @param groupId
     * @return
     */
    public boolean joinGroupDo(String groupId,String userId){
        Group group = this.getById(groupId);
        if(Objects.isNull(group)){
            return false;
        }
        Integer nowNumber = group.getNowNumber();
        try {
            //增加组局人数
            group.setNowNumber(nowNumber+1);
            if(group.getStartNumber() - nowNumber == 1){
                //人满设为待开局
                group.setGroupType(1);
            }
            this.updateById(group);
            //用户加入组局
            UserGroup userGroup = new UserGroup();
            userGroup.setUserId(userId);
            userGroup.setGroupId(group.getGroupId());
            userGroup.setScriptId(group.getScriptId());
            userGroup.setShopId(group.getShopId());
            userGroup.setMasterId(group.getMasterId());
            userGroup.setCreatedTime(new Date());
            return userGroupService.save(userGroup);
        } catch (Exception e) {
            log.info("定金支付成功，用户加入组局失败："+e.getMessage());
        }
        return false;
    }

    /**
     * 小程序组局详情
     * @param groupId
     * @return
     */
    public GroupDetailVo webGroupDetail(String groupId){
        String userId = userService.getUserId();
        GroupDetailVo groupDetailVo = this.baseMapper.webGroupDetail(groupId);
        //ids换取names
        String cateNames = scriptService.getNamesByIds(groupDetailVo.getScriptCateId(), 0);
        groupDetailVo.setScriptCateName(cateNames);
        int scriptMinutes = (int) (groupDetailVo.getScriptTime()*60);
        Date endTime = HelpUtils.afterTime(groupDetailVo.getStartTime(),scriptMinutes);
        groupDetailVo.setEndTime(endTime);
        if(Objects.nonNull(userId)){
            UserAppointOrder appointOrder = userAppointOrderService.getOne(new QueryWrapper<UserAppointOrder>()
                    .lambda()
                    .eq(UserAppointOrder::getUserId, userId)
                    .eq(UserAppointOrder::getGroupId, groupId)
                    .eq(UserAppointOrder::getHasPay,1));
            if(Objects.nonNull(appointOrder)){
                groupDetailVo.setAppointOrderPay(1);
            }
            //门店用户详情
            ShopUser shopUser = shopUserService.getOne(new QueryWrapper<ShopUser>()
                    .lambda()
                    .eq(ShopUser::getUserId, userId)
                    .eq(ShopUser::getShopId, groupDetailVo.getShopId()));
            //增加组局访问量
            shopStatisticsService.grandShopStatisticsGroup(groupDetailVo.getShopId(),shopUser);
        }
        return groupDetailVo;
    }

    /**
     * 快上车
     * @return
     */
    public RecommendGroupVo getOneCar(String shopId){
        Group group = this.getOne(new QueryWrapper<Group>()
                .lambda().eq(Group::getShopId, shopId)
                .eq(Group::getGroupType, 0)
                .orderByDesc(Group::getNowNumber)
                .last("LIMIT 1"));
        if(Objects.isNull(group)){
            return null;
        }
        String groupId = group.getGroupId();
        return this.baseMapper.groupJoinUserList(groupId);
    }

    /**
     * 未成局列表
     * @param searchParams
     * @return
     */
    public PageModel<GroupListPageVo> groupList(GroupListSearchParams searchParams){
        Map<String,Object> pageMap = new HashMap<>();
        pageMap.put("page",String.valueOf(searchParams.getPage()));
        pageMap.put("pageSize",String.valueOf(searchParams.getPageSize()));

        String shopId = userService.getGlobalShopId();
        searchParams.setShopId(shopId);
        Page<GroupListPageVo> list = this.baseMapper.groupList(
                new PageQuery<Group>(pageMap).getPage(),searchParams);
        List<GroupListPageVo> records = list.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageModel<>(list, new ArrayList<>());
        }
        //过滤开局时间已到但人未满的局
        List<GroupListPageVo> groupList = records.stream().filter(p -> {
            boolean startTimeArrive = HelpUtils.compareDateToNow(DateUtil.parse(p.getStartTime(), "yyyy-MM-dd HH:mm"));
            //开局时间到了，人满了
            if(startTimeArrive && p.getNowNumber() >= p.getStartNumber()){
                return true;
            }else return !startTimeArrive;
        }).collect(Collectors.toList());
        //设置剧本类型名称
        for (GroupListPageVo item : groupList){
            String cateNames = scriptService.getNamesByIds(item.getScriptCateId(), 0);
            item.setScriptCateName(cateNames);
        }
        return new PageModel<>(list, groupList);
    }

    /**
     * 主持人组局列表
     * @param searchParams
     * @return
     */
    public List<MasterGroupListVo> masterGroupList(MasterGroupListSearchParams searchParams){
        return this.baseMapper.masterGroupList(searchParams);
    }

    /**
     * 店铺组局列表
     * @param searchParams
     * @return
     */
    public List<MasterGroupListVo> shopWebGroupList(ShopWebGroupListSearchParams searchParams){
        return this.baseMapper.shopWebGroupList(searchParams);
    }

    /**
     * 组局海报
     * @param groupId
     * @return
     */
    public QrCodeVo groupPoster(String groupId){
        Group group = this.getById(groupId);
        if(Objects.isNull(group)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"组局不存在");
        }
        Script script = scriptService.getById(group.getScriptId());
        String shopId = userService.getGlobalShopId();
        Shop shop = shopService.getById(shopId);
        QrCodeVo qrCodeVo = new QrCodeVo();
        String wxUnlimitedCode = commonService.getWxUnlimitedCode(group.getGroupId(), shopId, "pages/Bureau/Bureaudetail");
        qrCodeVo.setShopName(shop.getShopName());
        qrCodeVo.setLogo(shop.getLogo());
        qrCodeVo.setImageUrl(script.getCoverImage());
        qrCodeVo.setCodeTitle(script.getScriptName());
        qrCodeVo.setQrCode(wxUnlimitedCode);
        return qrCodeVo;
    }

    /**
     * 最新未支付完的组局
     * @return
     */
    public GroupDetailVo lastGroup(){
        String shopId = userService.getGlobalShopId();
        String groupId = this.baseMapper.lastGroup(shopId);
        if(StringUtils.isNotBlank(groupId)){
            GroupDetailVo groupDetailVo = this.baseMapper.webGroupDetail(groupId);
            //ids换取names
            String cateNames = scriptService.getNamesByIds(groupDetailVo.getScriptCateId(), 0);
            groupDetailVo.setScriptCateName(cateNames);
            int scriptMinutes = (int) (groupDetailVo.getScriptTime()*60);
            Date endTime = HelpUtils.afterTime(groupDetailVo.getStartTime(),scriptMinutes);
            groupDetailVo.setEndTime(endTime);
            return groupDetailVo;
        }
        return null;
    }
}